﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using Aluetjen.EMailService.Contract;
using Aluetjen.EmailService.Infrastructure;
using StructureMap;
using StructureMap.Pipeline;
using log4net;

namespace Aluetjen.EmailService.Agent
{
    public partial class Service1 : ServiceBase
    {
        private readonly ILog _log = LogManager.GetLogger(typeof (Service1));

        private Timer _hostRefreshTimer;
        private readonly object _hostRefreshSync = new object();

        private const int _hostRefereshIntervalMilliseconds = 10000;

        public Service1()
        {
            InitializeComponent();
        }

        public void RunAsConsole(string[] args)
        {
            OnStart(args);

            Console.WriteLine("Press key to stop...");
            Console.ReadKey();

            OnStop();
        }

        protected override void OnStart(string[] args)
        {
            _log.Info("Starting service...");

            IoC.Initialize();

            ObjectFactory.Configure(
                x =>
                    {
                        x.For<IHostManager>().Use<HostManager>();
                        x.For<HostContainer>().Singleton().Use<HostContainer>();
                        x.For<IBindingFactory>().Use<BindingFactory>();
                    });

            _log.Info("Initializing host manager and schedule refresh...");

            _hostRefreshTimer = new Timer(OpenMissingHosts, 0, Timeout.Infinite, Timeout.Infinite);
            _hostRefreshTimer.Change(0, _hostRefereshIntervalMilliseconds);
        }

        protected override void OnStop()
        {
            _log.Info("Stopping service...");

            _hostRefreshTimer.Change(Timeout.Infinite, Timeout.Infinite);

            if (!Monitor.TryEnter(_hostRefreshSync, _hostRefereshIntervalMilliseconds))
            {
                _log.WarnFormat("Host refresh did not finish within {0}ms. Trying to close all hosts anyways.",
                                _hostRefereshIntervalMilliseconds);
            }

            _log.Info("Shutting down endpoint hosts...");

            var hostManager = ObjectFactory.GetInstance<IHostManager>();
            hostManager.CloseAllEndpoints();
        }

        private void OpenMissingHosts(object state)
        {
            if (Monitor.TryEnter(_hostRefreshSync))
            {
                try
                {
                    _log.InfoFormat("Refresh list of endpoints and open new or close obsolete ones...");

                    
                    var hostManager = ObjectFactory.GetInstance<IHostManager>();
                    hostManager.OpenMissingEndpoints();
                }
                finally
                {
                    new HybridLifecycle().FindCache().DisposeAndClear();
                    Monitor.Exit(_hostRefreshSync);
                }
            }
        }
    }
}
